force re-mounting
1const App = () => {
2 const [page, setPage] = useState('issue');
3
4 return (
5 <>
6 {page === 'issue' && <Issue />}
7 {page === 'about' && <About />}
8 </>
9 );
10};
<Issue>
, <Aboute>
컴포넌트 내부에서 fetching
컴포넌트 re-mount로 이전 컴포넌트가 unmount되면, 이전에 요청하던 fetching의 Promise 콜백의 상태를 사용하는 코드도 동작하지 않는다.
비슷한 멍청했던 경험
1const { mutate: updateSettings } = useUpdateSettings({
2 onSuccess: () => {
3 queryClient.invalidateQueries(displayQueryKeys.settings());
4 updateLayout({ displayId, viewId, layout: changedWidgetListRef.current });
5 rest.onClose(); // <- updateLayout 실행하고 닫아서
6 },
7 onError: (error) => {
8 handleError(error);
9 warningToast();
10 },
11});
12
13const { mutate: updateLayout } = useUpdateLayout({
14 onSuccess: () => {
15 // <- 실행 안됨
16 queryClient.invalidateQueries(displayQueryKeys.viewMode({ displayId, viewId }));
17 },
18 onError: (error) => {
19 handleError(error);
20 warningToast();
21 },
22});
drop all previous results
위 방식 이상하다. useEffect의 cleanup 함수 이용 방식
Unmout, re-rendering 전에 조건을 변경한다.
1useEffect(() => {
2 // set this closure to "active"
3 let isActive = true;
4
5 fetch(`/some-data-url/${id}`)
6 .then((r) => r.json())
7 .then((r) => {
8 // if the closure is active - update state
9 if (isActive) {
10 setData(r);
11 }
12 });
13
14 return () => {
15 // set this closure to not active before next re-render
16 isActive = false;
17 };
18}, [id]);
cancel all previous requests
fetch options에 signal이라고 필드가 있는데, 이것을 위와 같이 이용하는 예제
/call
1useEffect(() => {
2 const controller = new AbortController();
3
4 fetch(url, { signal: controller.signal })
5 .then((r) => r.json())
6 .then((r) => {
7 setData(r);
8 });
9
10 return () => {
11 controller.abort();
12 };
13}, [url]);